home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-12-11 | 15.4 KB | 530 lines | [TEXT/MPS ] |
- /*
- File: CappuccinoScripting.cpp
-
- Contents: Implements scripting support.
-
- Written by: Troy Gaul
-
- Copyright: © 1995 by Apple Computer, Inc., all rights reserved.
- */
-
- // -- Compiler/Preprocessor Switches --
-
- #ifndef _COMPILERDEFS_
- #include "CompDefs.h"
- #endif
-
- // -- OpenDoc Utilities --
-
- #ifndef _EXCEPT_
- // Exceptions define several important macros (eg. CHECKENV)
- // which are used in the SOM method dispatch glue. If Except.h
- // is not included early enough, exceptions may not be thrown
- // correctly when returning from a SOM method with the "ev" parameter set.
- #include <Except.h>
- #endif
-
- // -- Cappuccino Includes --
-
- #ifndef _CAPPUCCINO_
- #include "Cappuccino.h"
- #endif
-
- #ifndef _CAPPUCCINOACTION_
- #include "CappuccinoAction.h"
- #endif
-
- #ifndef _CAPPUCCINOCONTENT_
- #include "CappuccinoContent.h"
- #endif
-
- #ifndef SOM_CappuccinoSI_xh
- #include "som_CappuccinoSI.xh"
- #endif
-
- // -- OpenDoc Includes --
-
- #ifndef SOM_ODNameResolver_xh
- #include <NamRslvr.xh>
- #endif
-
- #ifndef SOM_ODAppleEvent_xh
- #include <ODAplEvt.xh>
- #endif
-
- #ifndef SOM_ODOSLToken_xh
- #include <ODOSLTkn.xh>
- #endif
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- // -- OpenDoc Utilities --
-
- #ifndef _ODMEMORY_
- #include <ODMemory.h>
- #endif
-
- #ifndef _ODDESUTL_
- #include <ODDesUtl.h>
- #endif
-
- #ifndef _ODUTILS_
- #include <ODUtils.h>
- #endif
-
- #ifndef _SEUTILS_
- #include <SEUtils.h>
- #endif
-
- #ifndef _SIHELPER_
- #include <SIHelper.h>
- #endif
-
- #ifndef _TEMPOBJ_
- #include <TempObj.h>
- #endif
-
- // -- Macintosh Includes --
-
- #ifndef __AEOBJECTS__
- #include <AEObjects.h>
- #endif
-
- #ifndef __AEREGISTRY__
- #include <AERegistry.h>
- #endif
-
- #ifndef _LIMITS
- #include <limits.h>
- #endif
-
- //==============================================================================
- #pragma mark • Utility functions/macros •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Macro
- //------------------------------------------------------------------------------
-
- // Just a convenience definition.
- #define NULL_DESCRIPTOR_DEFINITION {typeNull, NULL}
-
- //------------------------------------------------------------------------------
- // Function: GetDirectParam
- // Origin: Cappuccino
- //------------------------------------------------------------------------------
-
- static void GetDirectParam( ODSession* session,
- AppleEvent* message,
- AEDesc* evtDp )
- {
- Environment* ev = somGetGlobalEnvironment();
- AEDesc localDP = NULL_DESCRIPTOR_DEFINITION;
- ODNameResolver* resolver = session->GetNameResolver(ev);
-
- // Get the direct parameter
- THROW_IF_ERROR(AEGetParamDesc(message, keyDirectObject, typeWildCard,
- &localDP));
-
- // Make an ODDesc from it.
- ODOSLToken* tmpWrapper = new ODOSLToken;
- TempODObject tmpWrapperTemp = tmpWrapper;
- THROW_IF_NULL(tmpWrapper);
- tmpWrapper->InitODOSLToken(ev);
-
- THROW_IF_ERROR(AEDescToODDesc(&localDP, tmpWrapper));
-
- // Is it an OD token?
- if ( resolver->IsODToken(ev, tmpWrapper) )
- {
- *evtDp = localDP;
- }
- else
- {
- AEDisposeDesc(&localDP);
- THROW(errAEEventNotHandled);
- }
- }
-
- //==============================================================================
- #pragma mark • Stub callbacks •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // GetPropertyFromNULLStub
- //------------------------------------------------------------------------------
-
- static pascal ODError GetPropertyFromNULLStub( ODPart* part,
- DescType desiredClass,
- ODOSLToken* container,
- DescType containerClass,
- DescType form,
- ODDesc* selectionData,
- ODOSLToken* value,
- ODSLong refcon )
- {
- ODError error = noErr;
-
- TRY
- Environment* ev = somGetGlobalEnvironment();
- Cappuccino* self = (Cappuccino*) refcon;
-
- self->GetPropertyFromNULL(ev, desiredClass, container, containerClass,
- form, selectionData, value);
- CATCH_ALL
- error = ErrorCode();
- ENDTRY
-
- return error;
- }
-
- //------------------------------------------------------------------------------
- // HandleSetDataGetStub
- //------------------------------------------------------------------------------
-
- static pascal ODError HandleSetDataStub( ODPart* part,
- ODAppleEvent* message,
- ODAppleEvent* reply,
- ODSLong refcon )
- {
- ODError error = noErr;
-
- TRY
- Environment* ev = somGetGlobalEnvironment();
- Cappuccino* self = (Cappuccino*) refcon;
-
- self->HandleSetData(ev, message, reply);
- CATCH_ALL
- error = ErrorCode();
- ENDTRY
-
- return error;
- }
-
- //------------------------------------------------------------------------------
- // HandleGetDataStub
- //------------------------------------------------------------------------------
-
- static pascal ODError HandleGetDataStub( ODPart* part,
- ODAppleEvent* message,
- ODAppleEvent* reply,
- ODSLong refcon )
- {
- ODError error = noErr;
-
- TRY
- Environment* ev = somGetGlobalEnvironment();
- Cappuccino* self = (Cappuccino*) refcon;
-
- self->HandleGetData(ev, message, reply);
- CATCH_ALL
- error = ErrorCode();
- ENDTRY
-
- return error;
- }
-
- //==============================================================================
- #pragma mark • Cappuccino Scripting •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Method: ConstructSemanticInterface
- // Origin: Cappuccino
- //------------------------------------------------------------------------------
-
- void Cappuccino::ConstructSemanticInterface( Environment* ev )
- {
- // The following lines must be used in strict order in order to initalize
- // The CappuccinoSI and SIHelper classes correctly.
- fSemanticInterface = new som_CappuccinoSI;
- THROW_IF_NULL(fSemanticInterface);
-
- SIHelper* semItfcHelper = new SIHelper;
- semItfcHelper->InitSIHelper(fSession, fSemanticInterface);
-
- // The Extension interface requires that a pointer to the real part, not the
- // part wrapper, be passed to InitExtension. Therefore, we get that
- // reference here.
- ODPart* realPart = fSelf->GetRealPart(ev);
- fSemanticInterface->InitCPlusSemanticInterface(ev, realPart, semItfcHelper, fSession);
- fSelf->ReleaseRealPart(ev);
-
- SIHelper* helper = (SIHelper*) fSemanticInterface->GetSIHelper(ev);
-
- // We install one object accessor in order to get a token for the contents
- // property and two event handlers to handle get data and set data.
-
- ODObjectAccessorUPP theAccessorUPP;
-
- theAccessorUPP = NewODObjectAccessorProc(GetPropertyFromNULLStub);
- helper->InstallObjectAccessor(cProperty, typeNull, theAccessorUPP,
- (ODSLong) this);
-
- ODEventHandlerUPP theEventHandlerUPP;
-
- theEventHandlerUPP = NewODEventHandlerProc(HandleSetDataStub);
- helper->InstallEventHandler(kAECoreSuite, kAESetData, theEventHandlerUPP,
- (ODSLong) this);
-
- theEventHandlerUPP = NewODEventHandlerProc(HandleGetDataStub);
- helper->InstallEventHandler(kAECoreSuite, kAEGetData, theEventHandlerUPP,
- (ODSLong) this);
- }
-
- //------------------------------------------------------------------------------
- // Method: GetPropertyFromNULL
- // Origin: Cappuccino
- //------------------------------------------------------------------------------
-
- void Cappuccino::GetPropertyFromNULL( Environment* ev,
- DescType desiredClass,
- ODOSLToken* container,
- DescType containerClass,
- DescType form,
- ODDesc* selectionData,
- ODOSLToken* value )
- {
- ODNameResolver* resolver = fSession->GetNameResolver(ev);
-
- // We throw errAEEventNotHandled so that OpenDoc's default Semantic
- // Interface will try to handle this access even if we couldnt't
- if (form != formPropertyID)
- THROW(errAEEventNotHandled);
-
- AEDesc realData = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc realDataTemp = &realData;
- THROW_IF_ERROR(ODDescToAEDesc(selectionData, &realData));
-
- DescType propID = FIRSTBYTESFROMHANDLE(realData.dataHandle, DescType);
-
- switch ( propID )
- {
- case pContents:
- {
- // Create a descriptor that represents the object that we are
- // being asked for. For this object, which is the contents
- // property, we choose to set the descriptorType to cProperty
- // and to put the id of the property into the first four bytes
- // of the handle of the descriptor. We could have chosen a
- // different representation if we wanted to. It is also
- // common to instantiate a C++ object and place a reference to
- // it in the dataHandle of the token.
- AEDesc tokenDesc = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc tokenDescTemp = &tokenDesc;
- THROW_IF_ERROR(AECreateDesc(cProperty, &propID, sizeof(propID),
- &tokenDesc));
-
- // If your part's contents vary from display frame to display
- // frame then use the below code to determine which frame this
- // object access applies to.
- // ODPart* contextPart;
- // ODFrame* contextFrame;
- // resolver->GetContextFromToken(ev, container, &contextPart,
- // &contextFrame);
-
- // This utility routine gets the user token from the token and
- // updates it with the data passed in. See SEUtils.cpp.
- UpdateUserToken(ev, resolver, value, &tokenDesc);
- }
- break;
-
- default:
- THROW(errAEEventNotHandled); // let the default try
- break;
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: HandleSetData
- // Origin: Cappuccino
- //------------------------------------------------------------------------------
-
- void Cappuccino::HandleSetData( Environment* ev,
- ODAppleEvent* message,
- ODAppleEvent* reply )
- {
- ODNameResolver* resolver = fSession->GetNameResolver(ev);
-
- // Get an AEDesc version of our Apple event.
- AppleEvent realMessage = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc realMessageTemp = &realMessage;
- THROW_IF_ERROR(ODDescToAEDesc(message, &realMessage));
-
- // Get the data that will using for "setting".
- AEDesc theData = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc theDataTemp = &theData;
- THROW_IF_ERROR(AEGetKeyDesc(&realMessage, keyAEData, typeWildCard, &theData));
-
- AEDesc token = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc tokenTemp = &token;
- {
- // We need to create an ODDesc version of this so that we can call the
- // OpenDoc routines IsODToken and GetUserToken with it.
- ODOSLToken* tokenODDesc = new ODOSLToken;
- TempODObject tokenODDescTemp = tokenODDesc;
- THROW_IF_NULL(tokenODDesc);
- tokenODDesc->InitODOSLToken(ev);
- {
- // Get the direct parameter of the event. This will be our token.
- AEDesc evtDp = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc evtDpTemp = &evtDp;
- GetDirectParam(fSession, &realMessage, &evtDp);
-
- THROW_IF_ERROR(AEDescToODDesc(&evtDp, tokenODDesc));
- }
-
- // We might not actually get a token in the direct parameter. We
- // need to make sure it's an ODToken.
- if ( !resolver->IsODToken(ev, tokenODDesc) )
- THROW(errAENoSuchObject);
-
- // Get the "user" token. This is the one that we have actually
- // modified in our object accessor routine earlier.
- ODDesc* myTokenODDesc;
- myTokenODDesc = resolver->GetUserToken(ev, tokenODDesc);
-
- // Get an AEDesc version of same. Note that we could have extracted the
- // data using ODDesc::GetRawData as well.
- THROW_IF_ERROR(ODDescToAEDesc(myTokenODDesc, &token));
- }
-
- switch ( token.descriptorType )
- {
- case typeProperty:
- {
- // We know that if the descriptorType is typeProperty, we
- // earlier placed a property ID DescType in the first four
- // bytes of the dataHandle.
- DescType propID = FIRSTBYTESFROMHANDLE(token.dataHandle, DescType);
-
- if ( propID != pContents )
- THROW(errAEEventNotHandled);
-
- ThrowIfCantCoerce(&theData, typeChar);
-
- // Get the data out of the dataHandle and change our
- // private data.
- Size textLength = GetHandleSize(theData.dataHandle);
- THROW_IF_ERROR(MemError());
- if (textLength > UCHAR_MAX)
- THROW(errAEEventNotHandled);
-
- // Put the text into a string.
- Str255 string;
- string[0] = textLength;
- ODBlockMove(*theData.dataHandle, &string[1], textLength);
-
- // Create a new content object for the string.
- CCappuccinoContent* content = new CCappuccinoContent(this);
- TempRefCounted contentTemp = content;
- content->InitCappuccinoContent(ev, string);
-
- // Create an action and do it.
- CSetTextAction* action = new CSetTextAction(this, content);
- action->Perform(ev);
- }
- break;
-
- default:
- THROW(errAEEventNotHandled);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: HandleGetData
- // Origin: Cappuccino
- //------------------------------------------------------------------------------
-
- void Cappuccino::HandleGetData( Environment* ev,
- ODAppleEvent* message,
- ODAppleEvent* reply )
- {
- ODNameResolver* resolver = fSession->GetNameResolver(ev);
-
- // Get AEDesc versions of the event and the reply
- AppleEvent realMessage = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc realMessageTemp = &realMessage;
- THROW_IF_ERROR(ODDescToAEDesc(message, &realMessage));
-
- AppleEvent realReply = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc realReplyTemp = &realReply;
- THROW_IF_ERROR(ODDescToAEDesc(reply, &realReply));
-
- AEDesc token = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc tokenTemp = &token;
- {
- ODOSLToken* tokenODDesc = new ODOSLToken;
- TempODObject tokenODDescTemp = tokenODDesc;
- THROW_IF_NULL(tokenODDesc);
- tokenODDesc->InitODOSLToken(ev);
-
- // Get the direct parameter which will contain our token. We must also
- // create an ODDesc version so that we can call the OpenDoc methods
- // IsODToken and GetUserToken.
- {
- AEDesc evtDp = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc evtDpTemp = &evtDp;
- GetDirectParam(fSession, &realMessage, &evtDp);
-
- THROW_IF_ERROR(AEDescToODDesc(&evtDp, tokenODDesc));
- }
-
- // We might not actually get a token in the direct parameter. We
- // need to make sure it's an ODToken.
- if ( !resolver->IsODToken(ev, tokenODDesc) )
- THROW(errAENoSuchObject);
-
- // Get the "user" token which contains the token that we set up earlier.
- ODDesc* myTokenODDesc = resolver->GetUserToken(ev, tokenODDesc);
- THROW_IF_ERROR(ODDescToAEDesc(myTokenODDesc, &token));
- }
-
- // Next, get the requested return type, if it exists.
- DescType reqType;
- {
- Size theSize;
- OSErr error = AEGetParamPtr(&realMessage, keyAERequestedType, typeType,
- &reqType, (Ptr) &reqType, sizeof(reqType), &theSize);
-
- // Not an error if return type is not found -- use wildcard type.
- if (error == errAEDescNotFound)
- reqType = typeWildCard;
- else
- THROW_IF_ERROR(error);
- }
-
- AEDesc objectData = NULL_DESCRIPTOR_DEFINITION;
- TempAEDesc objectDataTemp = &objectData;
-
- switch ( token.descriptorType )
- {
- case typeProperty:
- // Create a descriptor containing our data. We try to coerce
- // it if we were asked for a type that's different from the
- // one we would ordinarily create.
- CCappuccinoContent* content = this->GetContent();
-
- THROW_IF_ERROR(AECreateDesc(typeChar, &content->GetString()[1],
- content->GetString()[0], &objectData));
-
- if ( reqType != typeChar && reqType != typeWildCard )
- ThrowIfCantCoerce(&objectData, reqType);
- break;
-
- default:
- THROW(errAEEventNotHandled);
- }
-
- // Place the result data into the reply
- THROW_IF_ERROR(AEPutParamDesc(&realReply, keyAEResult, &objectData));
-
- // Update the ODDesc version of the reply. The AEDesc version is just
- // a local copy that we use so that we can use all the AE manager
- // routines on it.
- THROW_IF_ERROR(AEDescToODDesc(&realReply, reply));
- }
-
-